/**
 * OrderServiceImpl.java
 * 
 * Copyright@2015 OVT Inc. All rights reserved. 
 * 
 * 2015年12月21日
 */
package com.ovt.order.service;

import java.text.MessageFormat;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ovt.common.exception.OVTRuntimeException;
import com.ovt.common.utils.NumberGeneratorUtil;
import com.ovt.order.dao.OrderDao;
import com.ovt.order.dao.RefundRequestDao;
import com.ovt.order.dao.TransferRequestDao;
import com.ovt.order.dao.contant.OrderState;
import com.ovt.order.dao.vo.Order;
import com.ovt.order.dao.vo.OrderItem;
import com.ovt.order.dao.vo.RefundRequest;
import com.ovt.order.dao.vo.TransferRequest;
import com.ovt.order.service.exception.ServiceErrorCode;
import com.ovt.order.service.exception.ServiceException;
import com.ovt.order.service.utils.StateChecker;

/**
 * OrderServiceImpl
 * 
 * @Author brad.zhou
 * @Version 1.0
 * @See
 * @Since [OVT Cloud Platform]/[API] 1.0
 */
@Service
public class OrderServiceImpl implements OrderService
{
    @Autowired
    private OrderDao orderDao;

    @Autowired
    private TransferRequestDao transferRequestDao;

    @Autowired
    private RefundRequestDao refundRequestDao;

    private static int ORDER_DELETE_FLAG_NOT_DELETE = 0;

    private static int ORDER_DELETE_FLAG_DELETE = 1;

    @Override
    public Order createOrder(long userId, float totalFee, String remark,
            List<OrderItem> productList) throws ServiceException
    {
        if (totalFee <= 0)
        {
            throw new ServiceException(ServiceErrorCode.INVALID_TOTAL_FEE,
                    "The totalFee must be a positive value!");
        }

        Order order = new Order();
        order.setUserId(userId);
        order.setOrderTotalFee(totalFee);
        order.setOrderNo(NumberGeneratorUtil.generateOrderNumber(userId));
        order.setOrderRemark(remark);
        order.setOrderState(OrderState.ORDER_WAIT_PAY);
        order.setIsDelete(0);
        order.setOrderItemList(productList);

        orderDao.saveOrder(order);

        return order;
    }

    @Override
    public List<Order> queryOrderList(long userId) throws ServiceException
    {
        List<Order> orderList = null;
        try
        {
            orderList = orderDao.getOrderList(userId);
        }
        catch (OVTRuntimeException e)
        {
            String message = MessageFormat.format(
                    "Failed to get all order list of user [{0}]", userId);
            throw new ServiceException(ServiceErrorCode.DB_SERVER_ERROR,
                    message, e);
        }

        return orderList;
    }

    @Override
    public Order queryOrderInfo(String orderNo) throws ServiceException
    {
        Order order = null;
        try
        {
            order = orderDao.getOrderInfo(orderNo);
            if (order == null)
            {
                throw new ServiceException(
                        ServiceErrorCode.INVALID_ORDER_NUMBER,
                        "Invalid orderNo!");
            }
        }
        catch (OVTRuntimeException e)
        {
            String message = MessageFormat.format(
                    "Failed to get detail info of order [{0}]", orderNo);
            throw new ServiceException(ServiceErrorCode.DB_SERVER_ERROR,
                    message, e);
        }

        return order;
    }

    @Override
    public Order queryOrderInfo(long userId, String orderNo)
            throws ServiceException
    {
        Order order = queryOrderInfo(orderNo);
        if (order.getUserId() != userId)
        {
            throw new ServiceException(
                    ServiceErrorCode.MISMATCH_USER_ID,
                    "Cannot find the correct order,"
                            + "the userId is mismatch between "
                            + "method argument and object that is query from DB!");
        }

        return order;

    }

    @Override
    public Order cancelOrder(long userId, String orderNo)
            throws ServiceException
    {
        Order order = queryOrderInfo(userId, orderNo);
        OrderState state = order.getOrderState();
        if (StateChecker
                .checkStateChangeValid(state, OrderState.ORDER_CANCELED))
        {
            try
            {
                orderDao.updateOrderState(orderNo, OrderState.ORDER_CANCELED);
                order.setOrderState(OrderState.ORDER_CANCELED);
            }
            catch (OVTRuntimeException e)
            {
                String message = MessageFormat.format(
                        "Failed to update state of order [{0}]", orderNo);
                throw new ServiceException(ServiceErrorCode.DB_SERVER_ERROR,
                        message, e);
            }

        }
        else
        {
            throw new ServiceException(ServiceErrorCode.INVALID_ORDER_STATE,
                    "Invalid order state!");
        }

        return order;
    }

    @Override
    public Order deleteOrder(long userId, String orderNo)
            throws ServiceException
    {
        Order order = queryOrderInfo(userId, orderNo);
        OrderState state = order.getOrderState();
        if (StateChecker.checkStateChangeValid(state, OrderState.ORDER_DELETE))
        {
            try
            {
                orderDao.updateOrderDeleteFlag(orderNo,
                        ORDER_DELETE_FLAG_DELETE);
                order.setIsDelete(ORDER_DELETE_FLAG_DELETE);
            }
            catch (OVTRuntimeException e)
            {
                String message = MessageFormat.format(
                        "Failed to update deleteFlag of order [{0}]", orderNo);
                throw new ServiceException(ServiceErrorCode.DB_SERVER_ERROR,
                        message, e);
            }

        }
        else
        {
            throw new ServiceException(ServiceErrorCode.INVALID_ORDER_STATE,
                    "Invalid order state!");
        }

        return order;
    }

    @Override
    public String applyForRefund(long userId, String orderNo,
            int refundReasonId, float refundFee, String refundDesc)
            throws ServiceException
    {
        Order order = queryOrderInfo(userId, orderNo);
        OrderState state = order.getOrderState();
        if ((order.getIsDelete() == ORDER_DELETE_FLAG_NOT_DELETE)
                && (StateChecker.checkStateChangeValid(state,
                        OrderState.REFUND_APPLYING)))
        {
            RefundRequest refundRequest = new RefundRequest();
            refundRequest.setOrderNo(orderNo);
            refundRequest.setRefundReasonId(refundReasonId);
            refundRequest.setRefundFee(refundFee);
            refundRequest.setRefundDesc(refundDesc);
            refundRequest.setRefundState(OrderState.REFUND_APPLYING);

            try
            {
                refundRequestDao.saveRefundRequest(refundRequest);
            }
            catch (OVTRuntimeException e)
            {
                String message = MessageFormat.format(
                        "Failed to insert refundRequest [{0}] into DB, [{0}]",
                        orderNo);
                throw new ServiceException(ServiceErrorCode.DB_SERVER_ERROR,
                        message, e);
            }

        }
        else
        {
            throw new ServiceException(ServiceErrorCode.INVALID_ORDER_STATE,
                    "Invalid order state!");
        }

        return orderNo;
    }

    @Override
    public List<RefundRequest> queryRefundRequestList() throws ServiceException
    {
        List<RefundRequest> refundRequestList = null;
        try
        {
            refundRequestList = refundRequestDao.queryAllRefundRequestList();
        }
        catch (OVTRuntimeException e)
        {
            String message = "Failed to get all refundRequest list";
            throw new ServiceException(ServiceErrorCode.DB_SERVER_ERROR,
                    message, e);
        }

        return refundRequestList;
    }

    @Override
    public List<TransferRequest> queryTransferRequestList()
            throws ServiceException
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<RefundRequest> queryRefundRequestList(List<Long> requestIdList)
            throws ServiceException
    {
        List<RefundRequest> refundRequestList = null;
        try
        {
            refundRequestList = refundRequestDao.queryRefundRequestList(requestIdList);
        }
        catch (OVTRuntimeException e)
        {
            String message = "Failed to get refundRequest list";
            throw new ServiceException(ServiceErrorCode.DB_SERVER_ERROR,
                    message, e);
        }

        return refundRequestList;
    }

    public OrderState setOrderState(String orderNo, OrderState state)
            throws ServiceException
    {
        orderDao.updateOrderState(orderNo, state);
        return state;
    }

    @Override
    public OrderState setRefundRequestListState(List<Long> requestIdList,
            OrderState state) throws ServiceException
    {
        return refundRequestDao.updateRefundRequestListState(requestIdList, state);
    }

    @Override
    public void putAuditorId(List<Long> requestIdList, Long auditorId)
            throws ServiceException
    {
        refundRequestDao.updateAuditorId(requestIdList, auditorId);
    }

    /* (non-Javadoc)
     * @see com.ovt.service.OrderService#setRefundRequestList(java.util.List, com.ovt.dao.contant.OrderState, long)
     */
    @Override
    public OrderState setRefundRequestList(List<Long> requestIdList,
            OrderState state, long auditorId) throws ServiceException
    {
        refundRequestDao.updateRefundRequestList(requestIdList, state, auditorId);
        return state;
    }

    /* (non-Javadoc)
     * @see com.ovt.service.OrderService#setRefundRequestList(java.util.List, com.ovt.dao.contant.OrderState, long, java.lang.String)
     */
    @Override
    public OrderState setRefundRequestList(List<Long> requestIdList,
            OrderState state, long auditorId, List<String> feedback)
            throws ServiceException
    {
        refundRequestDao.updateRefundRequestList(requestIdList, state, auditorId, feedback);
        return state;
    }


}
